package com.hzp.micromall.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hzp.micromall.common.core.api.CommonPage;
import com.hzp.micromall.product.dao.*;
import com.hzp.micromall.product.dto.PmsProductParam;
import com.hzp.micromall.product.dto.PmsProductQueryParam;
import com.hzp.micromall.product.dto.PmsProductResult;
import com.hzp.micromall.product.entity.*;
import com.hzp.micromall.product.feign.CmsPrefrenceAreaProductRelationService;
import com.hzp.micromall.product.feign.CmsSubjectProductRelationService;
import com.hzp.micromall.product.service.PmsProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author houzipeng
 * @Date 2022/2/26 16:11
 * @Version 1.0
 * 商品管理Service实现类
 */
@Slf4j
@Service
public class PmsProductServiceImpl implements PmsProductService {

    @Autowired
    private PmsProductDao productDao;
    @Autowired
    private PmsProductLadderDao productLadderDao;
    @Autowired
    private PmsProductFullReductionDao productFullReductionDao;
    @Autowired
    private PmsSkuStockDao skuStockDao;
    @Autowired
    private PmsProductAttributeValueDao productAttributeValueDao;
//    @Autowired
//    private CmsSubjectProductRelationService subjectProductRelationService;
//    @Autowired
//    private CmsPrefrenceAreaProductRelationService prefrenceAreaProductRelationDao;

    @Override
    public int create(PmsProductParam productParam) {
        int count;
        //创建商品
        PmsProduct product = productParam;
        product.setId(null);
        productDao.insert(product);
        //根据促销类型设置价格：会员价格、阶梯价格、满减价格
        Long productId = product.getId();
        //阶梯价格
        relateAndInsertList(productLadderDao, productParam.getProductLadderList(), productId);
        //满减价格
        relateAndInsertList(productFullReductionDao, productParam.getProductFullReductionList(), productId);
        //处理sku的编码
        handleSkuStockCode(productParam.getSkuStockList(), productId);
        //添加sku库存信息
        relateAndInsertList(skuStockDao, productParam.getSkuStockList(), productId);
        //添加商品参数,添加自定义商品规格
        relateAndInsertList(productAttributeValueDao, productParam.getProductAttributeValueList(), productId);
        // TODO: 2022/2/27 调用Cms的服务
        //关联专题
//        relateAndInsertList(subjectProductRelationDao, productParam.getSubjectProductRelationList(), productId);
        //关联优选
//        relateAndInsertList(prefrenceAreaProductRelationDao, productParam.getPrefrenceAreaProductRelationList(), productId);
        count = 1;
        return count;
    }

    @Override
    public int update(Long id, PmsProductParam productParam) {
        int count;
        //更新商品信息
        PmsProduct product = productParam;
        product.setId(id);
        productDao.updateById(product);
        //阶梯价格
        LambdaQueryWrapper<PmsProductLadder> proLadWrapper = new LambdaQueryWrapper<>();
        proLadWrapper.eq(PmsProductLadder::getProductId, id);
        productLadderDao.delete(proLadWrapper);
        relateAndInsertList(productLadderDao, productParam.getProductLadderList(), id);
        //满减价格
        LambdaQueryWrapper<PmsProductFullReduction> proFullReductionWrapper = new LambdaQueryWrapper<>();
        proFullReductionWrapper.eq(PmsProductFullReduction::getProductId, id);
        productFullReductionDao.delete(proFullReductionWrapper);
        relateAndInsertList(productFullReductionDao, productParam.getProductFullReductionList(), id);
        //修改sku库存信息
        handleUpdateSkuStockList(id, productParam);
        //修改商品参数,添加自定义商品规格
        LambdaQueryWrapper<PmsProductAttributeValue> proAttValWrapper = new LambdaQueryWrapper<>();
        proAttValWrapper.eq(PmsProductAttributeValue::getProductId, id);
        productAttributeValueDao.delete(proAttValWrapper);
        relateAndInsertList(productAttributeValueDao, productParam.getProductAttributeValueList(), id);
        // TODO: 2022/2/27 远程调用cms服务
        //关联专题
//        CmsSubjectProductRelationExample subjectProductRelationExample = new CmsSubjectProductRelationExample();
//        subjectProductRelationExample.createCriteria().andProductIdEqualTo(id);
//        subjectProductRelationMapper.deleteByExample(subjectProductRelationExample);
//        relateAndInsertList(subjectProductRelationDao, productParam.getSubjectProductRelationList(), id);
        //关联优选
//        CmsPrefrenceAreaProductRelationExample prefrenceAreaExample = new CmsPrefrenceAreaProductRelationExample();
//        prefrenceAreaExample.createCriteria().andProductIdEqualTo(id);
//        prefrenceAreaProductRelationMapper.deleteByExample(prefrenceAreaExample);
//        relateAndInsertList(prefrenceAreaProductRelationDao, productParam.getPrefrenceAreaProductRelationList(), id);
        count = 1;
        return count;
    }

    @Override
    public int updatePublishStatus(List<Long> ids, Integer publishStatus) {
        PmsProduct record = new PmsProduct();
        record.setPublishStatus(publishStatus);
        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(PmsProduct::getId, ids);
        return productDao.update(record, wrapper);
    }

    @Override
    public int updateRecommendStatus(List<Long> ids, Integer recommendStatus) {
        PmsProduct record = new PmsProduct();
        record.setRecommandStatus(recommendStatus);
        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(PmsProduct::getId, ids);
        return productDao.update(record, wrapper);
    }

    @Override
    public int updateNewStatus(List<Long> ids, Integer newStatus) {
        PmsProduct record = new PmsProduct();
        record.setNewStatus(newStatus);
        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(PmsProduct::getId, ids);
        return productDao.update(record, wrapper);
    }

    @Override
    public int updateDeleteStatus(List<Long> ids, Integer deleteStatus) {
        PmsProduct record = new PmsProduct();
        record.setDelStatus(deleteStatus);
        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(PmsProduct::getId, ids);
        return productDao.update(record, wrapper);
    }

    @Override
    public PmsProductResult getProduct(Long id) {
        return productDao.getProduct(id);
    }

    @Override
    public CommonPage<PmsProduct> getPage(PmsProductQueryParam productQueryParam, Integer pageSize, Integer pageNum) {
        Page<PmsProduct> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PmsProduct::getDelStatus, 0);
        if (productQueryParam.getPublishStatus() != null) {
            wrapper.eq(PmsProduct::getPublishStatus, productQueryParam.getPublishStatus());
        }
        if (StrUtil.isNotEmpty(productQueryParam.getKeyword())) {
           wrapper.like(PmsProduct::getKeywords, productQueryParam.getKeyword());
        }
        if (StrUtil.isNotEmpty(productQueryParam.getProductSn())) {
            wrapper.eq(PmsProduct::getProductSn, productQueryParam.getProductSn());
        }
        if (productQueryParam.getBrandId() != null) {
            wrapper.eq(PmsProduct::getBrandId, productQueryParam.getBrandId());
        }
        if (productQueryParam.getProductCategoryId() != null) {
            wrapper.eq(PmsProduct::getProductCategoryId, productQueryParam.getProductCategoryId());
        }
        productDao.selectPage(page, wrapper);
        return new CommonPage<>(page.getCurrent(), page.getTotal(), page.getSize(), page.getRecords());
    }

    @Override
    public List<PmsProduct> list(String keyword) {
        LambdaQueryWrapper<PmsProduct> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PmsProduct::getDelStatus, 0);
        if(StrUtil.isNotEmpty(keyword)){
            wrapper.like(PmsProduct::getKeywords, keyword);
            wrapper.or().eq(PmsProduct::getDelStatus, 0).like(PmsProduct::getProductSn, keyword);
        }
        return productDao.selectList(wrapper);
    }

    /**
     * 建立和插入关系表操作
     *
     * @param dao       可以操作的dao
     * @param dataList  要插入的数据
     * @param productId 建立关系的id
     */
    private void relateAndInsertList(Object dao, List dataList, Long productId) {
        try {
            if (CollUtil.isEmpty(dataList)) {
                return;
            }
            for (Object item : dataList) {
                Method setId = item.getClass().getMethod("setId", Long.class);
                setId.invoke(item, (Long) null);
                Method setProductId = item.getClass().getMethod("setProductId", Long.class);
                setProductId.invoke(item, productId);
            }
            Method insertList = dao.getClass().getMethod("insertList", List.class);
            insertList.invoke(dao, dataList);
        } catch (Exception e) {
            log.warn("创建产品出错:{}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    private void handleSkuStockCode(List<PmsSkuStock> skuStockList, Long productId) {
        if (CollUtil.isEmpty(skuStockList)) {
            return;
        }
        for (int i = 0; i < skuStockList.size(); i++) {
            PmsSkuStock skuStock = skuStockList.get(i);
            if (StringUtils.isEmpty(skuStock.getSkuCode())) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                StringBuilder sb = new StringBuilder();
                //日期
                sb.append(sdf.format(new Date()));
                //四位商品id
                sb.append(String.format("%04d", productId));
                //三位索引id
                sb.append(String.format("%03d", i + 1));
                skuStock.setSkuCode(sb.toString());
            }
        }
    }

    private void handleUpdateSkuStockList(Long id, PmsProductParam productParam) {
        //当前的sku信息
        List<PmsSkuStock> currSkuList = productParam.getSkuStockList();
        //当前没有sku直接删除
        if(CollUtil.isEmpty(currSkuList)){
            LambdaQueryWrapper<PmsSkuStock> skuStockWrapper = new LambdaQueryWrapper<>();
            skuStockWrapper.eq(PmsSkuStock::getProductId, id);
            skuStockDao.delete(skuStockWrapper);
            return;
        }
        //获取初始sku信息
        LambdaQueryWrapper<PmsSkuStock> skuStockWrapper = new LambdaQueryWrapper<>();
        skuStockWrapper.eq(PmsSkuStock::getProductId, id);
        List<PmsSkuStock> oriStuList = skuStockDao.selectList(skuStockWrapper);
        //获取新增sku信息
        List<PmsSkuStock> insertSkuList = currSkuList.stream().filter(item->item.getId()==null).collect(Collectors.toList());
        //获取需要更新的sku信息
        List<PmsSkuStock> updateSkuList = currSkuList.stream().filter(item->item.getId()!=null).collect(Collectors.toList());
        List<Long> updateSkuIds = updateSkuList.stream().map(PmsSkuStock::getId).collect(Collectors.toList());
        //获取需要删除的sku信息
        List<PmsSkuStock> removeSkuList = oriStuList.stream().filter(item-> !updateSkuIds.contains(item.getId())).collect(Collectors.toList());
        handleSkuStockCode(insertSkuList,id);
        handleSkuStockCode(updateSkuList,id);
        //新增sku
        if(CollUtil.isNotEmpty(insertSkuList)){
            relateAndInsertList(skuStockDao, insertSkuList, id);
        }
        //删除sku
        if(CollUtil.isNotEmpty(removeSkuList)){
            List<Long> removeSkuIds = removeSkuList.stream().map(PmsSkuStock::getId).collect(Collectors.toList());
            LambdaQueryWrapper<PmsSkuStock> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(PmsSkuStock::getId, removeSkuIds);
            skuStockDao.delete(wrapper);
        }
        //修改sku
        if(CollUtil.isNotEmpty(updateSkuList)){
            for (PmsSkuStock pmsSkuStock : updateSkuList) {
                skuStockDao.updateById(pmsSkuStock);
            }
        }
    }
}
